#include "factory.h"
//传输文件子函数
int tran_file(int new_fd,train_state_t *ct)
{
    printf("start sending!!\n");
    train_t t;
    int ret,size;
    char buf[1000]={0};
    int data_len;
    printf("trandile %d\n",ct->cmd_type);
    printf("file_name=%s\n",ct->file_name);
    char file_path[100]= "./USRSFILE/";
    strcat(file_path,ct->file_name);
    if(ct->cmd_type==GETS)
    {
        download(new_fd);
    }
    else{
        upload(new_fd);
    }
}
//服务器端将文件发送给客户端
int download(int new_fd)
{
    //接收文件名
    int data_len;
    char buf[1000]={0};
    int ret=recv_n(new_fd,&data_len,4);//接文件名长度
    SELFFUNC_ERR_CHECK(ret,"recv_n");
    ret=recv_n(new_fd,buf,data_len);//接文件名
    SELFFUNC_ERR_CHECK(ret,"recv_n");
    int fd=open(buf,O_WRONLY|O_CREAT,0666);
    ERROR_CHECK(fd,-1,"open");
    //接受文件大小
    ret=recv_n(new_fd,&data_len,4);
    SELFFUNC_ERR_CHECK(ret,"recv_n");
    //download_size当前大小，last_size是上次大小
    off_t file_size,download_size=0,last_size=0;
    ret=recv_n(new_fd,&file_size,data_len);//接文件大小
    SELFFUNC_ERR_CHECK(ret,"recv_n");
    off_t slice_size=file_size/10000;
    //接收文件内容
    ret=ftruncate(fd,file_size);
    void* p=mmap(NULL,file_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    ERROR_CHECK(p,(void*)-1,"mmap");
    ret=recv_n_show(new_fd,p,file_size);
    SELFFUNC_ERR_CHECK(ret,"recv_n");
    ret=munmap(p,file_size);
    ERROR_CHECK(ret,-1,"munmap");
}
//服务器端下载从客户端发送的文件
int upload(int new_fd)
{
    int fd=open(FILENAME,O_RDONLY);
    ERROR_CHECK(fd,-1,"open");
    //发送文件名
    int ret;
    train_t t;
    t.data_len=strlen(FILENAME);//文件名长度装在火车头
    strcpy(t.buf,FILENAME);
    ret=send_n(new_fd,&t,4+t.data_len);
    SELFFUNC_ERR_CHECK(ret,"send_n");
    //发送文件大小给客户端
    struct stat buf;
    ret=stat(FILENAME,&buf);
    ERROR_CHECK(ret,-1,"stat");
    t.data_len=sizeof(buf.st_size);
    memcpy(t.buf,&buf.st_size,sizeof(buf.st_size));
    ret=send_n(new_fd,&t,4+t.data_len);
    SELFFUNC_ERR_CHECK(ret,"send_n");
    //发送文件内容
    void* p=mmap(NULL,buf.st_size,PROT_READ,MAP_SHARED,fd,0);
    ERROR_CHECK(p,(void*)-1,"mmap");
    ret=send_n(new_fd,p,buf.st_size);
    SELFFUNC_ERR_CHECK(ret,"send_n");
    t.data_len=0;
    munmap(p,buf.st_size);
    return 0;
}

//循环接收数据，直到接收到自己想要数量
int recv_n(int sfd,void* buf,int data_len)
{
    char *p=(char*)buf;
    int total=0,ret;
    while(total<data_len)
    {
        ret=recv(sfd,p+total,data_len-total,0);
        total+=ret;
    }
    return 0;
}


//循环发送数据，直到发送到自己想要数量
int send_n(int sfd,void* buf,int data_len)
{
    char *p=(char*)buf;
    int total=0,ret;
    while(total<data_len)
    {
        ret=send(sfd,p+total,data_len-total,0);
        if(-1==ret)//代表对端断开了
        {
            return -1;
        }
        total+=ret;
    }
    return 0;
}

//循环接收数据，能够显示接收数据进度
int recv_n_show(int sfd,void* buf,int data_len)
{
    char *p=(char*)buf;
    int total=0,ret;
    off_t slice_size=data_len/10000;//文件的万分之一大小
    off_t last_size=0;//上一次大小
    while(total<data_len)
    {
        ret=recv(sfd,p+total,data_len-total,0);
        if(ret==-1)//对端断开
        {
            return -1;
        }
        total+=ret;
        if(total-last_size>slice_size)//打印进度
        {
            printf("%6.2lf%%\r",(double)total/data_len*100);
            fflush(stdout);
            last_size=total;
        }
    }
    printf("100.00%%\n");
    return 0;
}
//注册、监控
int epoll_add(int epfd,int fd)
{
    struct epoll_event event;
    event.data.fd=fd;//注册
    event.events=EPOLLIN;//是否可读
    int ret=epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&event);
    ERROR_CHECK(ret,-1,"epoll_ctl_add");
    return 0;
}